﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using DataProcessor.Core;
using LumenWorks.Framework.IO.Csv;

namespace DataProcessor.DeeplinkData
{
    public class MsraDataProcessor
    {
        public IEnumerable<Video> Videos { get; private set; }

        public MsraDataProcessor(string msraVideosPath, string engDownloadedVideoIdsPath)
        {
            // Read all english and downloaded MSRA videos
            Videos = new CsvReader(new StreamReader(msraVideosPath), true).ToCsvDictionary()
                 .Select(i => new Video(i))
                 .Join(File.ReadAllLines(engDownloadedVideoIdsPath), v => v.VideoId, vid => vid, (v, vid) => v)
                 .ToList();
        }

        public void PrintBasicResults()
        {
            int count = Videos.Count();

            var categories = Videos.GroupBy(v => v.Category)
                .Select(g => new
                {
                    Category = g.Key,
                    Count = g.Count()
                }).OrderByDescending(c => c.Count);

            var deeplinkVideos = Videos.Where(v => v.Deeplink == true);

            Console.WriteLine();
            Console.WriteLine("Total no. of english videos: " + count);
            Console.WriteLine("Total no. of deeplink videos: " + deeplinkVideos.Count());
            Console.WriteLine("Categories: " + categories.Count());
            categories.ToList().ForEach(c => Console.WriteLine(c.Category + " & " + c.Count + @"\\"));
        }

        public void FilterDataset(string dataset, string trainIdsFile, string outputFile)
        {
            var trainIds = new HashSet<string>(File.ReadAllLines(trainIdsFile));

            var csv = new CsvReader(new StreamReader(dataset), false)
                .Where(row => trainIds.Contains(row[0]))
                .Select(fields => fields.Aggregate((cur, next) => cur + ",\"" + next.Replace("\"", "\"\"") + "\"")).ToList();

            File.WriteAllLines(outputFile, csv);
        }

        public MsraDataProcessor Filter(string idsPath)
        {
            Videos = Videos.Join(File.ReadAllLines(idsPath), v => v.VideoId, vid => vid, (v, vid) => v);

            return this;
        }

        public void WriteDataset(string serverPath, string outputPath, bool deeplink, int count = 100)
        {
            var videoIds = Videos.Where(v => v.Deeplink == deeplink).Select(v => v.VideoId).Take(count);

            var paths = Directory.GetFiles(serverPath, "*.*", SearchOption.AllDirectories)
                .Where(f => videoIds.Any(v => f.Contains(v) && !f.Contains(".mp3"))).Distinct();
            
            var output = Videos.Join(videoIds, v => v.VideoId, vid => vid, (v, vid) => v)
                .Select(v => new { Video = v, Path = paths.Where(p => p.Contains(v.VideoId)).Single() })
                .Select(v => String.Format("{0},{1},{2}", v.Video.VideoId, v.Video.Deeplink, v.Path));

            var header = new string[] { "VideoId,Deeplink,AudioPath" };
            File.WriteAllLines(outputPath, header.Concat(output));
        }

        public void CreateFFMpegCommand(string videoPaths, string outputFile, string savePath = "")
        {
            var output = File.ReadAllLines(videoPaths).ToCsvDictionary()
                .Select(i => i["AudioPath"])
                .Select(f => String.Format("ffmpeg -i \"{0}\" \"{1}\"",
                f,
                String.IsNullOrEmpty(savePath) ?
                    (f.Substring(0, f.IndexOf('.')) + ".mp3").Insert(f.LastIndexOf('\\') + 1, "mp3\\") :
                    savePath + "\\" + f.Substring(f.LastIndexOf('\\') + 1, 11) + ".mp3"
                ));

            File.WriteAllLines(outputFile, output);
        }

        public void ListAudioFiles(string dirPath, string outputPath)
        { 
            var output = Directory.GetFiles(dirPath).Select(f => String.Format("{0},{1}",
                f.Substring(f.LastIndexOf('\\') + 1, 11), f));

            var header = new string[] { "VideoId,AudioPath" };
            File.WriteAllLines(outputPath, header.Concat(output));
        }


    }
}
